
package com.fdb.efp.batch.service.impl.hjwpzxbs;

import com.fdb.efp.batch.service.impl.hjwp.SynAccLoanVO;
import com.fdb.efp.batch.service.impl.hjwp.SynFileDataInterface;
import com.fdb.basic.framework.core.bean.TxtFileLoadBean;
import com.fdb.basic.framework.core.constant.DblStEnum;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.util.AccLoanStatusUtils;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.util.TxtFileLoadPlugin;
import com.fdb.efp.batch.service.facade.hjwpzxbs.SynZxbsAccloanService;
import com.fdb.efp.console.common.YedConstantSet;
import com.fdb.efp.console.common.psd.PsdConstantSet;
import com.fdb.efp.console.service.facade.PrdInfoService;
import com.fdb.efp.console.service.vo.PrdInfoVO;
import com.fdb.efp.loan.service.vo.AccLoanVO;
import com.fdb.efp.nls.service.facade.NlsApplyInfoService;
import com.fdb.efp.nls.service.vo.NlsApplyInfoVO;
import com.fdb.efp.report.service.facade.ZxbsAccLoanService;
import com.fdb.efp.report.service.facade.ZxbsLmtPrdContService;
import com.fdb.efp.report.service.facade.ZxbsLoanRepayPlanService;
import com.fdb.efp.report.service.vo.ZxbsAccLoanVO;
import com.fdb.efp.report.service.vo.ZxbsLmtPrdContVO;
import com.fdb.efp.report.service.vo.ZxbsLoanRepayPlanVO;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import static com.fdb.basic.framework.core.constant.BaseConstant.NLS_APPLY_STATE_01;
import static com.fdb.basic.framework.core.constant.BaseConstant.NLS_APPLY_STATE_02;

/**
 * 晚批同步互金借据、还款计划、还款信息数据-贷款台账同步
 *
 * @version 0.1
 */
@Service("synZxbsAccloanService")
public class SynZxbsAccloanServiceImpl implements SynZxbsAccloanService, SynFileDataInterface {

    private static Logger logger = LoggerFactory.getLogger(SynZxbsAccloanServiceImpl.class);

    //五级分类码值转换
    private static final HashMap<String, String> riskLevelMap = new HashMap();

    //还款方式
    private static final HashMap<String, String> repayModelMap = new HashMap();


    static {
        //五级分类
        //正常 关注 次级 可疑 损失
        riskLevelMap.put("01", "10");
        riskLevelMap.put("02", "20");
        riskLevelMap.put("03", "30");
        riskLevelMap.put("04", "40");
        riskLevelMap.put("05", "50");

        //还款方式
//        FB01	到期还本	4	按频率付息、一次还本
//        FB02	分期等额本金	2	等额本金
//        FB03	分期等额本息	1	等额本息
//        FB99	其他
//        FB04	一次还本付息	3	一次还本付息
        repayModelMap.put("4", "101");
        repayModelMap.put("2", "201");
        repayModelMap.put("1", "102");
        repayModelMap.put("3", "203");
    }

    @Autowired
    @Qualifier("zxbsAccLoanService")
    private ZxbsAccLoanService accLoanService;

    @Autowired
    @Qualifier("zxbsLoanRepayPlanService")
    private ZxbsLoanRepayPlanService accLoanRepayPlanService;

    @Autowired
    @Qualifier("prdInfoService")
    private PrdInfoService prdInfoService;

    @Autowired
    private NlsApplyInfoService nlsApplyInfoService;

    @Autowired
    private ZxbsLmtPrdContService zxbsLmtPrdContService;


    //@Value("${sed.loanFilePath}")
    private String loanFilePath = "/home/ocmuser/share/infile/psd/syncfile/";

    //@Value("${sed.accLoanFileNameDat}")
    private String fileNameOfDat = "idl_dm_loan_dubil_basic_info_i.$date$.dat";

    //@Value("${sed.accLoanFileNameOk}")
    private String fileNamOfOk = "idl_dm_loan_dubil_basic_info_i.$date$.ok";

    private PrdInfoVO currentPrdInfo = null;

    /**
     * 批次开始执行时间
     */
    private Date batchRunDate;

    /**
     * 批次日期
     */
    private String batchSubDate;

    /**
     * 需要更新额度信息的用信流水号
     */
    private ArrayList<String> updateLmtContNos = new ArrayList<>();

    @Override
    public Boolean syncAccloan(String subDate) throws Exception {
        //subDate = "2023-10-22";
        logger.info("批次时间：[{}]的互贷款台账同步批次开始运行", subDate);
        updateLmtContNos.clear();
        batchRunDate = new Date();
        batchSubDate = subDate;
        PrdInfoVO param = new PrdInfoVO();
        param.setPrdId(PsdConstantSet.prdId);
        param.setPrdCode(PsdConstantSet.prdId);
        currentPrdInfo = prdInfoService.queryByPrdCode(param);
        if (Objects.isNull(currentPrdInfo)) {
            throw new Exception("获取到的产品为空");
        }
        String fileUrl = loanFilePath + getCurrentBatchFileName(fileNameOfDat, subDate);
        //判断文件是否存在
        if (!new File(fileUrl).exists()) {
            logger.info("批次时间：[{}]的互贷款台账同步批次文件[{}]不存在", subDate, fileUrl);
            throw new Exception("数据文件不存在");
        }
        if (getOkFileDataNum(loanFilePath, fileNamOfOk, subDate) < 1) {
            logger.info("获取到的ok文件中的文件数据条数为空，不做处理");
            return Boolean.TRUE;
        }
        //校验ok文件
        if (!validateOkFile(getFileNum(fileUrl), loanFilePath, fileNamOfOk, subDate)) {
            return Boolean.FALSE;
        }
        TxtFileLoadPlugin txtFileLoadPlugin = new TxtFileLoadPlugin(fileUrl, "\u0002", "UTF-8", 0, 1000);
        List<TxtFileLoadBean> loanList = txtFileLoadPlugin.run(new SynAccLoanVO());
        dueData(loanList, subDate);
        if (loanList.size() != 0) {
            while (!loanList.get(loanList.size() - 1).isReadedComplete) {
                txtFileLoadPlugin.setFirstRead(false);
                loanList = txtFileLoadPlugin.run(new SynAccLoanVO());
                if (loanList.size() == 0) {
                    break;
                }
                dueData(loanList, subDate);
            }
        }

        if (updateLmtContNos.size() > 0) {
            updateLimit(updateLmtContNos);
        }

        return Boolean.TRUE;
    }

    private ArrayList<ZxbsAccLoanVO> insertOrUpdateAccloanVOs = new ArrayList<>();


    /**
     * 处理数据
     *
     * @param list
     * @param sub_date_date
     * @throws Exception
     */
    public void dueData(List<TxtFileLoadBean> list, String sub_date_date) throws Exception {
        //清空
        insertOrUpdateAccloanVOs.clear();
        //数据为空
        if (list == null) {
            return;
        }
        //数据为空
        if (list.isEmpty()) {
            return;
        }
        //根据文件数据获取当前需要处理的借据号（账户主键）
        List<String> ids = list.stream().map(a -> ((SynAccLoanVO) a).getId()).distinct().collect(Collectors.toList());
        // 根据借据号获取借据信息
        List<ZxbsAccLoanVO> accLoanVOList = accLoanService.queryByBillNos(ids);
        Map<String, ZxbsAccLoanVO> accLoanVOMap = new HashMap<>();
        //如果获取到的借据信息列表为空，那么新建一个空list
        if (accLoanVOList != null && accLoanVOList.size() > 0) {
            //转成map
            accLoanVOMap = accLoanVOList.stream().collect(Collectors.toMap(ZxbsAccLoanVO::getBillNo, a -> a, (K1, K2) -> K1));
        }
        //查询逾期的最小期数的还款计划
        List<ZxbsLoanRepayPlanVO> loanRepayPlanVOS = accLoanRepayPlanService.queryMinOverdueStmtDates(ids);
        Map<String, ZxbsLoanRepayPlanVO> loanRepayPlanVOMap = loanRepayPlanVOS.stream().collect(Collectors.toMap(ZxbsLoanRepayPlanVO::getRefNbr, b -> b, (K3, K4) -> K3));
        for (int i = 0; i < list.size(); i++) {
            SynAccLoanVO sedSynAccLoanVO = (SynAccLoanVO) list.get(i);
            ZxbsAccLoanVO accLoanVO = accLoanVOMap.get(sedSynAccLoanVO.getId());
            if (Objects.isNull(accLoanVO)) {
                logger.info(sedSynAccLoanVO.getId() + "在本地不存在");
                continue;
            }
            //如果借据为结清状态，那么不做处理
            if (DblStEnum.ENUM_4.getValue().equals(accLoanVO.getAccountStatus())&& (LocalDate.parse(accLoanVO.getBizDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd")).until(LocalDate.parse(batchSubDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")), ChronoUnit.DAYS) > 0)) {
                logger.info(sedSynAccLoanVO.getId() + "在本地已经是结清状态");
                continue;
            }
            try {
                // 账务日期
                setBizDate(sub_date_date,accLoanVO);
                //accLoanVO.setBizDate(sub_date_date);
                //支用合同号--用信申请流水号 --apply_seq---同步阶段改为用合同号作为用信申请流水号
                accLoanVO.setApplySeq(sedSynAccLoanVO.getContNo());
                accLoanVO.setLoanSeq(sedSynAccLoanVO.getLoanSeq());
                accLoanVO.setDistrNo(sedSynAccLoanVO.getDistrNo());
                //客户号--客户编号---客户编号不做更改
                //accLoanVO.setCusId(sedSynAccLoanVO.getCusId());
                //借据余额--借据余额
                accLoanVO.setLoanBalance(sedSynAccLoanVO.getLoanBalance());
                //未到期本金
                //逾期本金
                accLoanVO.setOverdueBalance(sedSynAccLoanVO.getOverduePrincipal());
                //贷款起始日--贷款起始日
                accLoanVO.setLoanStartDate(sedSynAccLoanVO.getLoanStartDate());
                //贷款终止日
                accLoanVO.setLoanEndDate(sedSynAccLoanVO.getLoanEndDate());
                //原到期日期
                accLoanVO.setOrigExpiDate(sedSynAccLoanVO.getLoanEndDate());
                //利息基准利率
                if (!Objects.isNull(sedSynAccLoanVO.getRulingIr())) {
                    accLoanVO.setRulingIr(sedSynAccLoanVO.getRulingIr().divide(BigDecimal.valueOf(100), 8, BigDecimal.ROUND_HALF_UP));
                }
                //利息执行年利率
                if (!Objects.isNull(sedSynAccLoanVO.getRealityIrY())) {
                    accLoanVO.setRealityIrY(sedSynAccLoanVO.getRealityIrY().divide(BigDecimal.valueOf(100), 8, BigDecimal.ROUND_HALF_UP));
                }
                // 累计结息-利息
                accLoanVO.setReceIntCumu(sedSynAccLoanVO.getRaceIntCumu());
                // 累计结息利息- 逾期利息
                //BigDecimal actualIntCumu = Optional.ofNullable(sedSynAccLoanVO.getRaceIntCumu()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(sedSynAccLoanVO.getOverdueInterest()).orElse(BigDecimal.ZERO));
                //accLoanVO.setActualIntCumu(actualIntCumu);
                // 欠息累计
                accLoanVO.setDelayIntCumu(sedSynAccLoanVO.getOverdueInterest());
                // 台账状态
                accLoanVO.setAccountStatus(AccLoanStatusUtils.transferAccStatusByHj(sedSynAccLoanVO.getAcctStatus(), sedSynAccLoanVO.getAccountStatus()));
                // w:正常贷款余额
                accLoanVO.setNormalBalance((sedSynAccLoanVO.getLoanBalance() == null ? BigDecimal.ZERO : sedSynAccLoanVO.getLoanBalance()).subtract(sedSynAccLoanVO.getOverduePrincipal() == null ? BigDecimal.ZERO : sedSynAccLoanVO.getOverduePrincipal()));
                // w:拖欠本金
                accLoanVO.setUnpdPrinBal(sedSynAccLoanVO.getLoanBalance());
                //设置逾期相关信息
                setOverdueInfo(loanRepayPlanVOMap, sedSynAccLoanVO, accLoanVO);
                // 结算日期
                setSettlDate(sedSynAccLoanVO, accLoanVO);
                // 利率类型 caoxin：互金不送了
                //accLoanVO.setIntRateType(sedSynAccLoanVO);
                // 利率增量选项 1 浮动值  2 浮动比 不确定
                //accLoanVO.setIntRateIncOpt();
                // 固定的罚息率 罚息执行年利率
                if (!Objects.isNull(sedSynAccLoanVO.getFixedRateIrY())) {
                    accLoanVO.setPrinFixedRate(sedSynAccLoanVO.getFixedRateIrY().divide(BigDecimal.valueOf(100), 8, BigDecimal.ROUND_HALF_UP));
                }
                // h:累计结息复利 w:应收复利累计
                accLoanVO.setUnpdArrPrnBal(sedSynAccLoanVO.getRaceReIntCumu());
                // 实收拖欠本金的罚息 累计结息罚息-逾期罚息
                //BigDecimal actArrsIntBal = Optional.ofNullable(sedSynAccLoanVO.getUnpdArrsPrnBa1()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(sedSynAccLoanVO.getOverdueCharge()).orElse(BigDecimal.ZERO));
                //accLoanVO.setActArrsIntBal(actArrsIntBal);
                //  实收复利  累计结息复利-逾期复利
                //BigDecimal actArrPrnBal = Optional.ofNullable(sedSynAccLoanVO.getRaceReIntCumu()).orElse(BigDecimal.ZERO).subtract(Optional.ofNullable(sedSynAccLoanVO.getCompIntRateInc()).orElse(BigDecimal.ZERO));
                //accLoanVO.setActArrPrnBal(actArrPrnBal);
                // 还款日
                accLoanVO.setReturnDate(sedSynAccLoanVO.getRepayDate());
                // 拖欠本金的罚息(应收未收)
                accLoanVO.setUnpdArrsIntBal1(sedSynAccLoanVO.getOverdueCharge());
                // h:逾期复利 w:应收未收的复利
                accLoanVO.setUnpdArrPrnBal1(sedSynAccLoanVO.getCompIntRateInc());
                // 欠息累计
                accLoanVO.setDelayIntCumu1(sedSynAccLoanVO.getUnpdArrsPrnBa1());
                // 还款方式
                String repayMode = repayModelMap.get(sedSynAccLoanVO.getRepaymentMode());
                if (StringUtil.isNotEmpty(repayMode)) {
                    accLoanVO.setRepaymentMode(repayMode);
                }
                // 五级分类
                if (!"2".equals(accLoanVO.getManualIdt())) {
                    accLoanVO.setClaPre(accLoanVO.getCla());
                    accLoanVO.setCla(riskLevelMap.get(sedSynAccLoanVO.getCla()));
                    accLoanVO.setClaDatePre(accLoanVO.getClaDate());
                    accLoanVO.setClaDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                }
                // 逾期天数
                accLoanVO.setOverdueDays(StringUtils.isEmpty(sedSynAccLoanVO.getOveerdueDay()) ? BigDecimal.ZERO : new BigDecimal(sedSynAccLoanVO.getOveerdueDay()));
                // 当前期数 取还款计划表开始日期《当前日期《到期日期 对应记录的期数
                accLoanVO.setCurrTerm(new BigDecimal(getCurrentTerm(accLoanVO)));
                // 最后修改日期
                accLoanVO.setLastUpdateTime(TimeUtil.getCurrentDateTime());

                insertOrUpdateAccloanVOs.add(accLoanVO);

            } catch (Exception e) {
                // 如果发生单笔异常 继续处理下一笔数据  记录借据号
                logger.error("【" + batchSubDate + "】号文件【晚批】更新借据" + accLoanVO.getBillNo() + "发生异常，信息为：", e);
                continue;
            }
        }
        if (insertOrUpdateAccloanVOs.size() > 0) {
            accLoanService.insertOrUpdate(insertOrUpdateAccloanVOs);
            updateLmtContNos.addAll(insertOrUpdateAccloanVOs.stream().map(a -> a.getLmtContNo()).distinct().collect(Collectors.toList()));
        }
    }

    private void setSettlDate(SynAccLoanVO sedSynAccLoanVO, ZxbsAccLoanVO accLoanVO) {
        if (StringUtils.isNotEmpty(sedSynAccLoanVO.getSettlementDate())) {
            try {
                //int i = TimeUtil.compareDates(sedSynAccLoanVO.getSettlementDate(), sedSynAccLoanVO.getLoanEndDate());
                //if (i == -1 || i == 0) {
                    accLoanVO.setSettlDate(sedSynAccLoanVO.getSettlementDate());
                //}else {
                   // accLoanVO.setSettlDate(LocalDate.parse(sedSynAccLoanVO.getSettlementDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(-1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                //}
                return;
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("时间转换出错");
            }
        }
        accLoanVO.setSettlDate(sedSynAccLoanVO.getSettlementDate());
    }

    private int getCurrentTerm(ZxbsAccLoanVO accLoanVO) {
        Integer integer = accLoanRepayPlanService.queryCurrentTerm(accLoanVO.getBizDate(), accLoanVO.getBillNo());
        if (integer == null) {
            return 0;
        }
        return integer.intValue();
    }

    private void setOverdueInfo(Map<String, ZxbsLoanRepayPlanVO> loanRepayPlanVOMap, SynAccLoanVO sedSynAccLoanVO, ZxbsAccLoanVO accLoanVO) throws Exception {
        if (loanRepayPlanVOMap.get(sedSynAccLoanVO.getId()) != null) {
            // 逾期起始日  期数最小的逾期到期日
            accLoanVO.setCapOverdueDate(loanRepayPlanVOMap.get(sedSynAccLoanVO.getId()).getStmtDate());
        }else {
            if (StringUtils.isNotEmpty(accLoanVO.getCapOverdueDate())) {
                accLoanVO.setCapOverdueDate(null);
            }
        }
        ArrayList<String> refNbrParams = new ArrayList<>();
        refNbrParams.add(sedSynAccLoanVO.getId());
        List<ZxbsLoanRepayPlanVO> repayPlanVOS = accLoanRepayPlanService.queryRepayPlansByRefNbr(refNbrParams);
        if (repayPlanVOS == null) {
            repayPlanVOS = new ArrayList<>();
        }
        // 当前逾期期数-查状态为逾期的还款计划数量
        accLoanVO.setOverTimesCurrent(new BigDecimal(repayPlanVOS.stream().filter(e -> "O".equals(e.getStatus())).count()));
        // 累计逾期期数-查逾期过（is_over_due=1）还款计划的数量
        accLoanVO.setOverTimesTotal(new BigDecimal(repayPlanVOS.stream().filter(e -> "1".equals(e.getIsOverDue())).count()));
        // 最高逾期期数-最高连续逾期的期数（查逾期过（is_over_due=1）的还款计划将 判断最大连续的个数）
        accLoanVO.setMaxTimesTotal(new BigDecimal(getMaxTimesTotal(repayPlanVOS.stream().filter(e -> "1".equals(e.getIsOverDue())).collect(Collectors.toList()))));
    }

    /**
     * 判断最高连续逾期次数: <br>
     * 0.1:caoxin:2019/6/27 18:50: 判断最高连续逾期次数 <br>
     *
     * @return
     * @author caoxin
     * @date 2019/6/27 18:50
     * @version 0.1
     * @since 2019/6/27 18:50
     */
    private int getMaxTimesTotal(List<ZxbsLoanRepayPlanVO> list) {
        if (list == null) {
            return 0;
        }
        if (list.size() <= 1) {
            return list.size();
        }
        //将list排序
        List<ZxbsLoanRepayPlanVO> collect = list.stream().sorted(Comparator.comparingInt(ZxbsLoanRepayPlanVO::getTerm)).collect(Collectors.toList());
        int maxSucc = 1;
        int temp = 1;
        for (int i = 1; i < collect.size(); i++) {
            if ((collect.get(i).getTerm() - 1) == collect.get(i - 1).getTerm()) {
                temp++;
            } else {
                if (temp > maxSucc) {
                    maxSucc = temp;
                }
                temp = 1;
            }
        }
        return maxSucc > temp ? maxSucc : temp;
    }

    private List<String> getSuccessApplySeq(String lmtApplySeq) {
        NlsApplyInfoVO nlsApplyInfoVo = new NlsApplyInfoVO();
        nlsApplyInfoVo.setLmtApplySeq(lmtApplySeq);
        nlsApplyInfoVo.setNlsApplyState(NLS_APPLY_STATE_02);
        List<NlsApplyInfoVO> nlsApplyInfoVs = Optional.ofNullable(nlsApplyInfoService.queryListByLmtApplySqe(nlsApplyInfoVo)).orElseGet(ArrayList::new);
        return nlsApplyInfoVs.stream().filter(Objects::nonNull).map(NlsApplyInfoVO::getApplySeq).collect(Collectors.toList());
    }

    private void normalTakeUpLmt(BigDecimal occAmt, BigDecimal preOccAmt, ZxbsLmtPrdContVO lmtPrdContVO) throws BizException {
        lmtPrdContVO.setOccAmt(occAmt);
        lmtPrdContVO.setPreOccAmt(preOccAmt);
        lmtPrdContVO.setAvailAmt(lmtPrdContVO.getLmtAmt().subtract(occAmt).subtract(preOccAmt));
        int result = zxbsLmtPrdContService.updateByPk(lmtPrdContVO);
        logger.info("额度恢复变更的条数为：[{}]", result);
    }

    private void updateLmtPro(String lmtContNo) {
        try {
            ZxbsLmtPrdContVO param = new ZxbsLmtPrdContVO();
            param.setLmtContNo(lmtContNo);
            ZxbsLmtPrdContVO zxbsLmtPrdContVO = zxbsLmtPrdContService.queryByPk(param);
            if (Objects.nonNull(zxbsLmtPrdContVO)) {
                List<String> successApplySeqs = getSuccessApplySeq(zxbsLmtPrdContVO.getLmtApplySeq());
                BigDecimal occAmt = getOccAmt(successApplySeqs);
                BigDecimal preOccAmt = getPreOccAmt(zxbsLmtPrdContVO.getLmtApplySeq());
                if (YedConstantSet.prdId.equals(zxbsLmtPrdContVO.getPrdId())){
                    preOccAmt = zxbsLmtPrdContVO.getPreOccAmt();
                }
                normalTakeUpLmt(occAmt, preOccAmt, zxbsLmtPrdContVO);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public BigDecimal getOccAmt(List<String> applySeqs) throws Exception {
        // 第一次支用申请时，已用额度为零
        if (null == applySeqs || applySeqs.isEmpty()) {
            return BigDecimal.ZERO;
        }
        // 通过用信申请流水号统计所有借据的借据余额
        List<ZxbsAccLoanVO> accLoanVOS = Optional.ofNullable(accLoanService.queryByApplySqes(applySeqs)).orElseGet(ArrayList::new);
        return accLoanVOS.
                stream().
                map(ZxbsAccLoanVO::getLoanBalance).
                filter(Objects::nonNull).
                reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    public BigDecimal getPreOccAmt(String lmtApplySeq) {
        logger.info("通过授信申请流水号【" + lmtApplySeq + "】,获取所有在途的用信申请信息开始------------------- 目前表示在途的状态有【处理中、挂起】");
        NlsApplyInfoVO nlsApplyInfoVo = new NlsApplyInfoVO();
        nlsApplyInfoVo.setLmtApplySeq(lmtApplySeq);
        nlsApplyInfoVo.setNlsApplyState(NLS_APPLY_STATE_01);
        List<NlsApplyInfoVO> nlsApplyInfoVs = Optional.ofNullable(nlsApplyInfoService.queryListByLmtApplySqe(nlsApplyInfoVo)).orElseGet(ArrayList::new);
        // 计算预占用额度
        return nlsApplyInfoVs.
                stream().
                map(NlsApplyInfoVO::getApplyAmt).
                filter(Objects::nonNull).
                reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 更新额度
     *
     * @param lmtContNos 用信申请流水号集合
     */
    private void updateLimit(List<String> lmtContNos) throws Exception {

        logger.info("互金晚批同步（征信报送），开始进行额度恢复");
        if (lmtContNos == null) {
            return;
        }
        if (lmtContNos.isEmpty()) {
            return;
        }
        List<List<String>> partition = ListUtils.partition(lmtContNos, 500);
        for (List<String> strings : partition) {
            for (String string : strings) {
                updateLmtPro(string);
            }
        }

    }

    private void setBizDate(String sub_date_date, ZxbsAccLoanVO accLoanVO) throws Exception {
        //查询放款时间
        //如果放款时间大于文件日期则使用放款时间
        String firstDisbDate = accLoanVO.getFirstDisbDate();
        int i = TimeUtil.compareDates(accLoanVO.getFirstDisbDate(), batchSubDate);
        if (i == 1) {
            accLoanVO.setBizDate(firstDisbDate);
            return;
        }
        accLoanVO.setBizDate(sub_date_date);
    }

    private void updateLmtProYed(String lmtContNo) {
        try {
            ZxbsLmtPrdContVO param = new ZxbsLmtPrdContVO();
            param.setLmtContNo(lmtContNo);
            ZxbsLmtPrdContVO zxbsLmtPrdContVO = zxbsLmtPrdContService.queryByPk(param);
            if (Objects.nonNull(zxbsLmtPrdContVO)) {
                List<String> successApplySeqs = getSuccessApplySeq(zxbsLmtPrdContVO.getLmtApplySeq());
                BigDecimal occAmt = getOccAmt(successApplySeqs);
                BigDecimal preOccAmt = zxbsLmtPrdContVO.getPreOccAmt();
                normalTakeUpLmt(occAmt, preOccAmt, zxbsLmtPrdContVO);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

